Track filter fix (#363)
authortsteven4 <13596209+tsteven4@users.noreply.github.com>
Wed, 29 May 2019 22:57:02 +0000 (16:57 -0600)
committerGitHub <noreply@github.com>
Wed, 29 May 2019 22:57:02 +0000 (16:57 -0600)
* Fix compatibility for track filter GUI<->CLI.

Add a week unit for the track filter move option,
in addition to the existing day, hour, minute and second units.

Allow combination of units for track filter move option, e.g.
1w2d3h4m-5s = 1 week + 2 days + 3 hours + 4 minutes - 5 seconds.
This matches historical use, and is expected by the GUI.

Add the week unit to the GUI track filter ui.

Change the limits on the track filter move specs:
week: +/-10000 (unit didn't exit before)
day,hour,minute,second: +/- 100000 (+/-2000 for day before, +/-100 on others).

This resolves #357.
This resolves #358.

* add documentation for track filter move option.

gui/filterdata.cc
gui/filterdata.h
gui/filterwidgets.cc
gui/trackui.ui
trackfilter.cc
xmldoc/filters/options/track-move.xml

index 092cabde8feb1529a914c3916ae73d5211403ce6..6fc304f14c10da3d22e1b1f4e6a6a308f47ac09a 100644 (file)
@@ -136,7 +136,7 @@ QStringList TrackFilterData::makeOptionString()
     s += QString(",stop=%1").arg(optionDate(stopTime, TZ));
   }
   if (move) {
-    s += QString(",move=%1d%2h%3m%4s").arg(days).arg(hours).arg(mins).arg(secs);
+    s += QString(",move=%1w%2d%3h%4m%5s").arg(weeks).arg(days).arg(hours).arg(mins).arg(secs);
   }
   if (title) {
     s += QString(",title=%1").arg(titleString);
index 2520847046668fee6b5535ca8700ec7aa3315309..5132493063797ce9ec1a7d30dfa2a0a3ae7eb03b 100644 (file)
@@ -60,7 +60,7 @@ class TrackFilterData: public FilterData
 {
 public:
   TrackFilterData(): FilterData(), title(false), titleString(QString()),
-    move(false),  days(0), hours(0), mins(0), secs(0),
+    move(false),  weeks(0), days(0), hours(0), mins(0), secs(0),
     TZ(false),
     start(false),
     stop(false),
@@ -98,6 +98,7 @@ public:
     sg.addVarSetting(new DateTimeSetting("trks.stopTime", stopTime));
     sg.addVarSetting(new BoolSetting("trks.TZ", TZ));
     sg.addVarSetting(new BoolSetting("trks.move", move));
+    sg.addVarSetting(new IntSetting("trks.weeks", weeks));
     sg.addVarSetting(new IntSetting("trks.days", days));
     sg.addVarSetting(new IntSetting("trks.mins", mins));
     sg.addVarSetting(new IntSetting("trks.hours", hours));
@@ -115,7 +116,7 @@ public:
   bool title;
   QString titleString;
   bool move;
-  int  days, hours, mins, secs;
+  int  weeks, days, hours, mins, secs;
   bool TZ;
 
   bool start;
index ee241ae1e7fcbfeba87fb43571ee5e7ccd5b4dc1..10cf9149617833da420fd84432455641143316b6 100644 (file)
@@ -32,6 +32,7 @@ TrackWidget::TrackWidget(QWidget* parent, TrackFilterData& tfd): FilterWidget(pa
   addCheckEnabler(ui.titleCheck, ui.titleText);
   addCheckEnabler(ui.moveCheck,
                   (QList<QWidget*> ()
+                   << ui.weeksLabel << ui.weeksSpin
                    << ui.daysLabel << ui.daysSpin
                    << ui.hoursLabel<< ui.hoursSpin
                    << ui.minsLabel << ui.minsSpin
@@ -76,10 +77,11 @@ TrackWidget::TrackWidget(QWidget* parent, TrackFilterData& tfd): FilterWidget(pa
   fopts << new BoolFilterOption(tfd.course, ui.courseCheck);
   fopts << new BoolFilterOption(tfd.speed,  ui.speedCheck);
 
-  fopts << new IntSpinFilterOption(tfd.days,  ui.daysSpin, -2000, 2000);
-  fopts << new IntSpinFilterOption(tfd.hours, ui.hoursSpin);
-  fopts << new IntSpinFilterOption(tfd.mins,  ui.minsSpin);
-  fopts << new IntSpinFilterOption(tfd.secs,  ui.secsSpin);
+  fopts << new IntSpinFilterOption(tfd.weeks,  ui.weeksSpin, ui.weeksSpin->minimum(), ui.weeksSpin->maximum());
+  fopts << new IntSpinFilterOption(tfd.days,  ui.daysSpin, ui.daysSpin->minimum(), ui.daysSpin->maximum());
+  fopts << new IntSpinFilterOption(tfd.hours, ui.hoursSpin, ui.hoursSpin->minimum(), ui.hoursSpin->maximum());
+  fopts << new IntSpinFilterOption(tfd.mins,  ui.minsSpin, ui.minsSpin->minimum(), ui.minsSpin->maximum());
+  fopts << new IntSpinFilterOption(tfd.secs,  ui.secsSpin, ui.secsSpin->minimum(), ui.secsSpin->maximum());
   fopts << new IntSpinFilterOption(tfd.splitTime,  ui.splitTimeSpin, 0, 1000);
   fopts << new IntSpinFilterOption(tfd.splitDist,  ui.splitDistSpin, 0, 5280);
 
index 9e42c93bfb5aed97649339b80eca2efec23f9a5e..172b7b04dfbc25a2bcd2c7f79b94c3a025621f92 100644 (file)
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>663</width>
-    <height>248</height>
+    <height>270</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -73,9 +73,43 @@ This option changes the time of all trackpoints. This might be useful if your tr
       </widget>
      </item>
      <item row="2" column="1">
+      <layout class="QHBoxLayout" name="horizontalLayout_9">
+       <item>
+        <widget class="QSpinBox" name="weeksSpin">
+         <property name="accelerated">
+          <bool>true</bool>
+         </property>
+         <property name="minimum">
+          <number>-10000</number>
+         </property>
+         <property name="maximum">
+          <number>10000</number>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QLabel" name="weeksLabel">
+         <property name="text">
+          <string>weeks</string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+     <item row="2" column="2">
       <layout class="QHBoxLayout" name="horizontalLayout_5">
        <item>
-        <widget class="QSpinBox" name="daysSpin"/>
+        <widget class="QSpinBox" name="daysSpin">
+         <property name="accelerated">
+          <bool>true</bool>
+         </property>
+         <property name="minimum">
+          <number>-100000</number>
+         </property>
+         <property name="maximum">
+          <number>100000</number>
+         </property>
+        </widget>
        </item>
        <item>
         <widget class="QLabel" name="daysLabel">
@@ -89,7 +123,17 @@ This option changes the time of all trackpoints. This might be useful if your tr
      <item row="2" column="3">
       <layout class="QHBoxLayout" name="horizontalLayout_4">
        <item>
-        <widget class="QSpinBox" name="hoursSpin"/>
+        <widget class="QSpinBox" name="hoursSpin">
+         <property name="accelerated">
+          <bool>true</bool>
+         </property>
+         <property name="minimum">
+          <number>-100000</number>
+         </property>
+         <property name="maximum">
+          <number>100000</number>
+         </property>
+        </widget>
        </item>
        <item>
         <widget class="QLabel" name="hoursLabel">
@@ -103,7 +147,17 @@ This option changes the time of all trackpoints. This might be useful if your tr
      <item row="2" column="4">
       <layout class="QHBoxLayout" name="horizontalLayout_2">
        <item>
-        <widget class="QSpinBox" name="minsSpin"/>
+        <widget class="QSpinBox" name="minsSpin">
+         <property name="accelerated">
+          <bool>true</bool>
+         </property>
+         <property name="minimum">
+          <number>-100000</number>
+         </property>
+         <property name="maximum">
+          <number>100000</number>
+         </property>
+        </widget>
        </item>
        <item>
         <widget class="QLabel" name="minsLabel">
@@ -117,7 +171,17 @@ This option changes the time of all trackpoints. This might be useful if your tr
      <item row="2" column="5">
       <layout class="QHBoxLayout" name="horizontalLayout">
        <item>
-        <widget class="QSpinBox" name="secsSpin"/>
+        <widget class="QSpinBox" name="secsSpin">
+         <property name="accelerated">
+          <bool>true</bool>
+         </property>
+         <property name="minimum">
+          <number>-100000</number>
+         </property>
+         <property name="maximum">
+          <number>100000</number>
+         </property>
+        </widget>
        </item>
        <item>
         <widget class="QLabel" name="secsLabel">
index 1778a989edacac5e01b7d179a6d300f0b2607f3d..c1a592e60729535d9b7a62fb6ffb122be1af7c36 100644 (file)
@@ -78,34 +78,42 @@ int TrackFilter::trackfilter_opt_count()
 
 qint64 TrackFilter::trackfilter_parse_time_opt(const char* arg)
 {
-  qint64 result;
+  qint64 result = 0;
 
-  QRegularExpression re("^([+-]?\\d+)([dhms])$", QRegularExpression::CaseInsensitiveOption);
+  QRegularExpression re("^([+-]?\\d+)([wdhms])(?:([+-]?\\d+)([wdhms]))?(?:([+-]?\\d+)([wdhms]))?(?:([+-]?\\d+)([wdhms]))?(?:([+-]?\\d+)([wdhms]))?$", QRegularExpression::CaseInsensitiveOption);
   assert(re.isValid());
   QRegularExpressionMatch match = re.match(arg);
   if (match.hasMatch()) {
-    bool ok;
-    result = match.captured(1).toLong(&ok);
-    if (!ok) {
-      fatal(MYNAME "-time: invalid quantity in move option \"%s\"!\n", qPrintable(match.captured(1)));
-    }
+    int lastindex = match.lastCapturedIndex();
+    for (int idx = 1; idx < lastindex; idx += 2) {
+      bool ok;
+      qint64 partial = match.captured(idx).toLong(&ok);
+      if (!ok) {
+        fatal(MYNAME "-time: invalid quantity in move option \"%s\"!\n", qPrintable(match.captured(idx)));
+      }
 
-    switch (match.captured(2).at(0).toLower().toLatin1()) {
-    case 'd':
-      result *= SECONDS_PER_DAY;
-      break;
-    case 'h':
-      result *= SECONDS_PER_HOUR;
-      break;
-    case 'm':
-      result *= 60;
-      break;
-    case 's':
-      break;
-    default:
-      fatal(MYNAME "-time: invalid unit in move option \"%s\"!\n", qPrintable(match.captured(2)));
-    }
+      switch (match.captured(idx+1).at(0).toLower().toLatin1()) {
+      case 'w':
+        partial *= SECONDS_PER_DAY * 7;
+        break;
+      case 'd':
+        partial *= SECONDS_PER_DAY;
+        break;
+      case 'h':
+        partial *= SECONDS_PER_HOUR;
+        break;
+      case 'm':
+        partial *= 60;
+        break;
+      case 's':
+        break;
+      default:
+        fatal(MYNAME "-time: invalid unit in move option \"%s\"!\n", qPrintable(match.captured(idx+1)));
+      }
 
+      result += partial;
+
+    }
 #ifdef TRACKF_DBG
     qDebug() << MYNAME "-time option: shift =" << result << "seconds";
 #endif
index 22452828aca50f485b3da20f5bff752e50590f2a..e3dd19ff736b9c20aaec705ba22668ee59d60535 100644 (file)
@@ -2,6 +2,13 @@
 This option changes the time of all trackpoints. This might be useful if
 your track must be moved by one or more hours because of an incorrect
 time zone.
+It can also be useful to correct tracks for week number roll over problems.
+</para>
+<para>
+The value of this option is a series of integer and unit pairs.  Each integer may include a
+leading '+' or '-' sign.  Positive integers shift the tracks later, while negative integers shift
+the tracks earlier.  If no sign is provided the integer is assumed to be nonnegative.
+Possible units are w for weeks, d for days, h for hours, m for minutes and s for seconds.
 </para>
 <example id="ex_track_move">
 <title>Time-shifting a track with the track filter</title>
@@ -10,4 +17,21 @@ The following command line will shift all tracks to be one hour later.
 </para>
 <para><userinput>gpsbabel -t -i gpx -f in.gpx -x track,move=+1h -o gpx -F out.gpx</userinput></para>
 </example>
+<example id="ex_track_move_wnro">
+<title>Time-shifting a track with the track filter to correct WNRO</title>
+<para>
+The following command line will shift all tracks to be 1024 weeks later.  Because the GPS Week Number
+is transmitted modulo 1024 there is the possibility that the recovered timestamp will be off by
+a multiple of 1024 weeks.
+</para>
+<para><userinput>gpsbabel -t -i gpx -f in.gpx -x track,move=+1024w -o gpx -F out.gpx</userinput></para>
+</example>
+<example id="ex_track_move_combo">
+<title>Time-shifting a track with the track filter with combined units</title>
+<para>
+The following command lines will each shift all tracks to be 1 hour and 1 minute earlier, i.e. 61 minutes earlier.
+</para>
+<para><userinput>gpsbabel -t -i gpx -f in.gpx -x track,move=-1h-1m -o gpx -F out.gpx</userinput></para>
+<para><userinput>gpsbabel -t -i gpx -f in.gpx -x track,move=-61m -o gpx -F out.gpx</userinput></para>
+</example>